<--- %%NOBANNER%% --> extlog.sas.sas
 BackForward

/*-------------------------------------------------------------------\
| This macro was written for two purposes:                           |
|  1. Users that have lost the original source code, but still have  |
|     the log, for a program that must be re-run.                    |
|  2. Transfering SAS macro code (with mprint turned on) from the    |
|     log into a runnable program.                                   |
|                                                                    |
|  This is a macro call with the syntax:                             |
|     _EXTLOG INFILE='input_log_file' FILE='output_file_name' ;      |
|                                                                    |
|  The program will read the log file, strip all of the line numbers,|
|  NOTES, WARNINGS, SAS headers, ERROR notices from the file.        |
|                                                                    |
|  There should be no problems extracting most SAS log files,        |
|  espeically if users do not write lines longer than 200 characters.|
|                                                                    |
|  If the file was generated from a macro the resolved macro code    |
|  will be saved.                                                    |
|                                                                    |
|  Any lines in the log that do not start with a number (or other    |
|  identifier) will not be removed.  These lines are usually         |
|  associated with the macro information that has been provided by   |
|  users at the Centre.  You will have to search for and delete these|
|  lines yourself.                                                   |
\-------------------------------------------------------------------*/
%macro extlog(infile= ,file=,debug=nodebug ) /stmt;
%* Test for required file information; 
%if &infile= %then %goto error;
%if &file= %then %goto error;

%* Turn on debuging notes if necessary;
%if %quote(%upcase(&debug)) = %quote(DEBUG) %then options mprint notes;
%else options nomprint nonotes;;

%* Create null data set for reading file information, and stripping lines;
data _null_;
   length line $200 macro $20 comment $1;
   retain cards  'N' err 'N' warn 'N' inval 'N' macro;
   infile &infile missover delimiter='~';
   %* Look for notes and other SAS log lines ;
   input  line & $200. ;
   if line =:'NOTE' |
      line=:'real' |
      line=:'cpu' |
      line=:'Engine'|
      line=:'Physical' |
      line=:'File' |
      line=:'Owner' |
      line=:'Access' |
      line=:'The m' then delete ;
   %* Test for errors and set warning flag;
   else if line=:'ERROR' then do;
      if err = 'N' then err='Y';
      delete;
   end;
   %* Test for SAS warnings and set flag;
   else if line=:'WARNING' then do;
      if warn = 'N' then warn='Y';
      delete;
      end;
   %* Strip the SAS page title;
   else if index(line,'The SAS') then delete;

   %* Stip intro lines from SAS log;
   else if index(line,'following SAS modules') then delete;
   else if index(line,'Welcome to the SAS') then delete;
   else if index(line,'Licensed to') then delete;
   else if index(line,'BASE GRAPH ETS') then delete;
   else if index(line,'CALC EIS') then delete;
   else if index(line,'$Id:') then delete;

   %* strp various other lines from the file;
   else if index(line,'compressed would require') then delete;

   %* strip string conversion notices;
   else if index(line,'Each place is given by') then do;
      inval = 'Y';
      delete;
   end;
   if inval = 'Y' then do;
      inval = 'N' ; delete;
   end;

   %* check if a cards statement was used. The data from
      card input is usually not printed to the log;
   if cards='N' & (index(line,'cards') | index(line,'CARDS')) then cards = 'Y';

   %* set all flags in macro variables;
   call symput('cards',cards);
   call symput('err',err);
   call symput('warn',warn);

   %* Define the output file;
   file &file;

   %* output SAS code.
   %* If the code comes from resolved macro code then
      output the resoved code.  If it is the first time
      the macro is encountered write a note to the code file;
   if line=:'MPRINT' | line=:'MACROGEN' then do;
      if macro ^= substr(line,1,indexc(line,':')) then do;
         macro = substr(line,1,indexc(line,':'));
         put;
         put '*** CODE FROM RESOLVED MACRO:'  macro ';';
      end;
     line = substr(line,indexc(line,':')+1);
   end;
   %* Some times resolved macro code is spread over several lines.
      The next line catches most (not all) of the multiple line
      resolved code.;
   else if ^('1' <= substr(line,1,1) <= '9') then line = line;
   %* What to do with all the normal SAS code;
   else line = substr(line,8);

   %* delete multiple blank lines ;
   %* Set a lag line variable.  This is used to testfor and remvoe
      blank lines.;
   lagline = lag(line);
   if line = '' & lagline = '' then delete;

   %* put the source code out into the file;
   put line;
run;
options nomprint notes;;
%if &cards = Y %then %put WARNING: CARDS statement found, data may not be available ;
%if &err = Y %then %put WARNING: ERROR notice was found in the log file ;
%if &warn = Y %then %put WARNING: WARNING notice was found in the log file ;
%put;
%put NOTE: Input log file &infile written to output sas file &file;
%put;
%goto exit;
%error:
   %put WARNING: One of the INFILE, or FILE options was missing;
   %put .        Syntax: _EXTLOG INFILE='log.file' FILE='output.file';
%exit:
%mend;

/*** Examples of how to call the macro ;
*_extlog infile='/home/burchil/testing/test.log'
         file='/home/burchil/testing/clean' ;
*_extlog infile='/PHIS/Hospital/testing/test.run.log'
         file='/home/burchil/testing/clean'  ;
***/
*_extlog infile='/home/burchil/hosp.service/rates.log' file='#junk#' ;
*_extlog infile='/home/burchil/testing/test.log' file='#junk#' ;